﻿using Levfier.Proccessors.Filters;
using Levfier.Proccessors.Parameters;
using System;

namespace Levfier.Proccessors.EQs
{
    /// <summary>
    /// Fender標準の3バンドイコライザー
    /// </summary>
    public class ThreeBandEQ : ProccessorSetBase
    {
        /// <summary>
        /// ロー
        /// </summary>
        private LowShelfIIR low;

        /// <summary>
        /// ハイ
        /// </summary>
        private HighShelfIIR high;

        /// <summary>
        /// ミドル
        /// </summary>
        private PeakIIR middle;

        /// <summary>
        /// ミドルの中心周波数
        /// </summary>
        private ProccessParameter middleFreqParam;

        /// <summary>
        /// 処理を行う
        /// </summary>
        /// <param name="input">入力</param>
        public override void Proccess(double[] input)
        {
            if(null == this.lowerChain)
            { 
                return;
            }

            if (this.bypass)
            {
                this.ProccessBypass(input, this.lowerChain.GetBuffer());
                this.lowerChain.FlowSounds();
            }
            else
            {
                //最後尾のhighにバッファチェインを設定
                this.high.SetLowerChain(this.lowerChain);

                // Low -> Mid -> Highの順で音を流す
                this.low.Proccess(input);
            }

            //↓自動的に呼び出される
            //後段のストリームへ流す
            //lowerChain.FlowSounds();
        }

        /// <summary>
        /// 使用しない
        /// </summary>
        /// <param name="inputBuffer">入力</param>
        /// <param name="outputBuffer">出力</param>
        protected override void InnerProccess(double[] inputBuffer, double[] outputBuffer)
        {
            //なにもしない
        }

        /// <summary>
        /// パラメータの初期化を行う
        /// </summary>
        protected override void InitParameters()
        {
            //イコライザを構成する
            this.low = new LowShelfIIR();
            this.high = new HighShelfIIR();
            this.middle = new PeakIIR();

            //接続する Low -> Mid -> Highの順で接続する
            this.ChainProccessors(this.low, this.middle);
            this.ChainProccessors(this.middle, this.high);

            //周波数の設定
            this.low.GetParameters()["Freq[Hz]"].Value = 500.0d;
            this.middle.GetParameters()["Freq[Hz]"].Value = 1000.0d;
            this.high.GetParameters()["Freq[Hz]"].Value = 2000.0d;

            this.low.GetParameters()["QFactor"].Value = (1.0d / Math.Sqrt(2.0d));
            this.middle.GetParameters()["QFactor"].Value = (1.0d / Math.Sqrt(2.0d));
            this.high.GetParameters()["QFactor"].Value = (1.0d / Math.Sqrt(2.0d));

            //画面に表示するため 名前を変更する
            this.low.GetParameters()["Gain[dB]"].Name = "Low[dB]";
            this.middle.GetParameters()["Gain[dB]"].Name = "Mid[dB]";
            this.middle.GetParameters()["QFactor"].Name = "Mid Contour";
            this.high.GetParameters()["Gain[dB]"].Name = "High[dB]";

            //ミドルの中心周波数
            this.middleFreqParam = new ProccessParameter();
            this.middleFreqParam.Name = "Mid Freq[Hz]";
            this.middleFreqParam.Value = 1000.0d;
            this.middleFreqParam.MaxValue = 2000.0d;
            this.middleFreqParam.MinValue = 0.0d;
            this.middleFreqParam.Step = 1.0d;
            //イベント登録
            this.middleFreqParam.ValueChanged += this.MiddleFreqParam_ValueChanged;

            this.parameters.Add(this.low.GetParameters()["Gain[dB]"].Name, this.low.GetParameters()["Gain[dB]"]);
            this.parameters.Add(this.middle.GetParameters()["Gain[dB]"].Name, this.middle.GetParameters()["Gain[dB]"]);
            this.parameters.Add(this.high.GetParameters()["Gain[dB]"].Name, this.high.GetParameters()["Gain[dB]"]);
            this.parameters.Add(this.middleFreqParam.Name, this.middleFreqParam);
            this.parameters.Add(this.middle.GetParameters()["QFactor"].Name, this.middle.GetParameters()["QFactor"]);
            
        }

        /// <summary>
        /// 中心周波数を変更した時の動作
        /// </summary>
        /// <param name="sender">イベント発生元</param>
        private void MiddleFreqParam_ValueChanged(object sender)
        {
            ProccessParameter senderParam = sender as ProccessParameter;
            this.low.GetParameters()["Freq[Hz]"].Value = senderParam.Value / 2.0d;
            this.high.GetParameters()["Freq[Hz]"].Value = senderParam.Value * 2.0d;
        }
    }
}
